﻿using mozhi.smarterp.Finance.Finances.Repository;
using mozhi.smarterp.Finance.Finances.Services.EndPeriodProcess;
using mozhi.smarterp.Finance.Querys;
using Mozhi.Abp.Core.Extensions;
using Mozhi.Abp.Domain.BasicData.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Domain.Services;

namespace mozhi.smarterp.Finance.Finances.Services
{
    public class EndPeriodProcessManager : DomainService
    {
        private IOrganizationRepository _organizationRepository;
        private ISettlementRepository _settlementRepository;
        private IJournalRepository _journalRepository;
        private IServiceProvider _serviceProvider;

        public EndPeriodProcessManager(IOrganizationRepository organizationRepository, IServiceProvider serviceProvider,
            ISettlementRepository settlementRepository, IJournalRepository journalRepository)
        {
            _organizationRepository = organizationRepository;
            _serviceProvider = serviceProvider;
            _settlementRepository = settlementRepository;
            _journalRepository = journalRepository;
        }

        public async Task<EndPeriodProcessResult> GetProcessResultAsync(EndPeriodProcessItem item, int period)
        {
            await Validate(period);

            var processor = EndPeriodProcessorFacotry.Instance(item, period, _serviceProvider);

            var result = await processor.GetProcessResultAsync();

            return result;
        }

        public async Task<Journal> GenerateJournal(EndPeriodProcessItem item, int period)
        {
            await Validate(period);

            var processor = EndPeriodProcessorFacotry.Instance(item, period, _serviceProvider);

            var result = await processor.GenerateJournal();

            return result;
        }

        #region
        private async Task Validate(int period)
        {
            var organization = await _organizationRepository.GetAsync();

            var initalBalancePeriod = organization.ActivatedDate.Value.ToPeriod().ToPrePeriod();

            var settlements = await _settlementRepository.FindAsync(new SettlementQuery() { Periods = new List<int>() { period, initalBalancePeriod } });

            var openingSettlement = settlements.FirstOrDefault(x => x.Period == initalBalancePeriod);

            if (openingSettlement == null)
                throw new UserFriendlyException($"组织未完成初始化", "100000");

            var settlement = settlements.FirstOrDefault(x => x.Period == period);

            if (settlement != null && settlement.Closed)
                throw new UserFriendlyException($"期间:{period}已结账", "100000");

            var unApprovedJournalCount = await _journalRepository.GetCountAsync(new JournalPageQuery() { Approved = false, StartPeriod = period, EndPeriod = period });

            if (unApprovedJournalCount > 0)
                throw new UserFriendlyException($"期间:{period}存在未审核凭证", "100000");
        }
        #endregion
    }
}
